﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
//using System.Linq;
using System.Net;
//using System.Text;
using System.Threading;
using System.Windows;
//using System.Windows.Controls;
//using System.Windows.Data;
//using System.Windows.Documents;
//using System.Windows.Input;
//using System.Windows.Media;
//using System.Windows.Media.Imaging;
//using System.Windows.Navigation;
//using System.Windows.Shapes;

namespace Restarter
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Thread ServerThread = null;
        private Process ServerProcess = null;
        private bool on = false;
        private List<string> ServerList = new List<string>();
        private byte Interval = 0;

        private void ProcurarServidor()
        {
            try
            {
                using (StreamReader _s = new StreamReader("servers.txt"))
                {
                    while (!_s.EndOfStream)
                    {
                        string _f = _s.ReadLine();
                        if (File.Exists(_f + ".exe"))
                        {
                            ServerList.Add(_f);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                tboxConsole.AppendText(DateTime.Now + " Erro ao ler arquivo servers.txt\nMensagem de erro: " + e.Message + "\n");
                return;
            }
            switch (ServerList.Count)
            {
                case 0: tboxConsole.AppendText(DateTime.Now + " Nenhum servidor padrão encontrado\n"); break;
                case 1: tboxServidor.Text = Directory.GetCurrentDirectory() + "\\" + ServerList[0] + ".exe"; tboxConsole.AppendText(DateTime.Now + " Servidor encontrado: " + ServerList[0] + ".exe\n"); break;
                default: tboxConsole.AppendText(DateTime.Now + " Foi encontrado mais de um servidor, por favor selecione manualmente.\n"); break;
            }
        }

        private void RestarterWorker()
        {
            try
            {
                uint x = 1;
                while (true)
                {
                    ServerProcess.WaitForExit();
                    tboxConsole.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate() { tboxConsole.AppendText(DateTime.Now + " O servidor caiu! Reiniciando automaticamente...\n"); }));
                    Thread.Sleep(new TimeSpan(0, 0, Interval));
                    if (Convert.ToBoolean(menuAutoRestart.Dispatcher.Invoke(new Func<bool>(() => { return !menuAutoRestart.IsChecked; }))))
                    {
                        if (MessageBox.Show("O servidor caiu! Deseja reiniciar?", "Atenção", MessageBoxButton.YesNo) == MessageBoxResult.No)
                        {
                            bttnParar.Dispatcher.Invoke(new Action(delegate() { bttnParar.Visibility = System.Windows.Visibility.Hidden; }));
                            bttnIniciar.Dispatcher.Invoke(new Action(delegate() { bttnIniciar.Visibility = System.Windows.Visibility.Visible; }));
                            tboxConsole.Dispatcher.Invoke(new Action(delegate() { tboxConsole.AppendText(DateTime.Now + " Servidor fechado.\n\n"); }));
                            on = false;
                            ServerThread.Abort();
                            return;
                        }
                    }
                    ServerProcess.Start();
                    on = true;
                    x++;
                    tboxConsole.Dispatcher.Invoke(new Action(delegate() { tboxConsole.AppendText(DateTime.Now + " Servidor iniciado " + x + " vezes...\n"); }));
                }
            }
            catch (ThreadAbortException)
            {
                tboxConsole.Dispatcher.Invoke(new Action(delegate() { tboxConsole.AppendText(DateTime.Now + " Thread desativado.\n\n"); }));
            }
            catch (Exception ex)
            {
                tboxConsole.Dispatcher.Invoke(new Action(delegate() { tboxConsole.AppendText(DateTime.Now + " Erro não detectado: " + ex.Message + "\n"); }));
            }
        }

        public MainWindow()
        {
            InitializeComponent();
        }

        private void bttnProcurar_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog _o = new Microsoft.Win32.OpenFileDialog();
            _o.DefaultExt = ".exe";
            _o.Filter = "Executáveis (.exe)|*.exe";

            if (_o.ShowDialog() == true)
            {
                tboxServidor.Text = _o.FileName;
                if (!ServerList.Exists(item => item == _o.SafeFileName))
                {
                    ServerList.Add(_o.SafeFileName);
                    using (StreamWriter _s = new StreamWriter(Directory.GetCurrentDirectory() + "\\servers.txt", true))
                    {
                        _s.WriteLine("\n" + _o.SafeFileName.Substring(0, _o.SafeFileName.Length - 4));
                    }
                }
            }
        }

        private void bttnIniciar_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string _s = tboxServidor.Text;
                if (MessageBox.Show("Deseja atualizar o IP configurado no config.lua?", "Atenção", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    StreamReader _r = new StreamReader(WebRequest.Create("http://checkip.dyndns.org/").GetResponse().GetResponseStream());
                    string config = File.ReadAllText(new FileInfo(tboxServidor.Text).DirectoryName + "\\config.lua");
                    string ip = "ip = \"" + new System.Text.RegularExpressions.Regex("[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}").Match(_r.ReadToEnd(), 0).Value + "\"";
                    //config = new System.Text.RegularExpressions.Regex("ip = \"[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}\"").Replace(config, ip);
                    config = new System.Text.RegularExpressions.Regex("ip = \"[a-zA-Z0-9.]\"").Replace(config, ip);
                    File.WriteAllText(new FileInfo(tboxServidor.Text).DirectoryName + "\\config.lua", config);
                }
                ServerProcess = System.Diagnostics.Process.Start(_s);
                ServerThread = new Thread(new ThreadStart(RestarterWorker));
                ServerThread.Start();
                tboxConsole.AppendText(DateTime.Now + " Thread iniciado.\n");
                on = true;
                tboxConsole.AppendText(DateTime.Now + " Servidor iniciado...\n");
                bttnIniciar.Visibility = System.Windows.Visibility.Hidden;
                bttnParar.Visibility = System.Windows.Visibility.Visible;
            }
            catch (FileNotFoundException)
            {
                MessageBox.Show("Servidor não encontrado! Procure novamente.");
                bttnParar.Visibility = System.Windows.Visibility.Hidden;
                bttnIniciar.Visibility = System.Windows.Visibility.Visible;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Erro não identificado: \n" + ex.Message);
                bttnParar.Visibility = System.Windows.Visibility.Hidden;
                bttnIniciar.Visibility = System.Windows.Visibility.Visible;
            }
        }

        private void bttnParar_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("Deseja realmente parar o restarter?", "Atenção", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                try
                {
                    if (MessageBox.Show("Deseja desligar o servidor?", "Atenção", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                    {
                        ServerProcess.Kill();
                        tboxConsole.AppendText(DateTime.Now + " Servidor desligado...\n");
                    }
                    ServerThread.Abort();
                    bttnParar.Visibility = System.Windows.Visibility.Hidden;
                    bttnIniciar.Visibility = System.Windows.Visibility.Visible;
                    on = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Houve um erro ao fechar o servidor!\n" + ex.Message);
                }
            }
        }

        private void menuFechar_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (on)
            {
                if (MessageBox.Show("Fechar o restarter irá fechar o servidor também. Tem certeza?", "Atenção", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    try
                    {
                        ServerThread.Abort();
                        if (!ServerProcess.HasExited)
                        {
                            ServerProcess.Kill();
                        }
                    }
                    finally
                    {
                        e.Cancel = false;
                    }
                }
                else
                {
                    e.Cancel = true;
                }
            }
        }

        private void menuNoInterval_Click(object sender, RoutedEventArgs e)
        {
            Interval = 0;
            menuNoInterval.IsChecked = true;
            menu1secInterval.IsChecked = false;
            menu5secInterval.IsChecked = false;
            menu15secInterval.IsChecked = false;
            menu60secInterval.IsChecked = false;
        }

        private void menu1secInterval_Click(object sender, RoutedEventArgs e)
        {
            Interval = 1;
            menuNoInterval.IsChecked = false;
            menu1secInterval.IsChecked = true;
            menu5secInterval.IsChecked = false;
            menu15secInterval.IsChecked = false;
            menu60secInterval.IsChecked = false;
        }

        private void menu5secInterval_Click(object sender, RoutedEventArgs e)
        {
            Interval = 5;
            menuNoInterval.IsChecked = false;
            menu1secInterval.IsChecked = false;
            menu5secInterval.IsChecked = true;
            menu15secInterval.IsChecked = false;
            menu60secInterval.IsChecked = false;
        }

        private void menu15secInterval_Click(object sender, RoutedEventArgs e)
        {
            Interval = 15;
            menuNoInterval.IsChecked = false;
            menu1secInterval.IsChecked = false;
            menu5secInterval.IsChecked = false;
            menu15secInterval.IsChecked = true;
            menu60secInterval.IsChecked = false;
        }

        private void menu60secInterval_Click(object sender, RoutedEventArgs e)
        {
            Interval = 60;
            menuNoInterval.IsChecked = false;
            menu1secInterval.IsChecked = false;
            menu5secInterval.IsChecked = false;
            menu15secInterval.IsChecked = false;
            menu60secInterval.IsChecked = true;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            tboxConsole.AppendText("<-- Restarter BETA -->\n");
            tboxConsole.AppendText(DateTime.Now + " Inicializando sistemas...\n");
            tboxConsole.AppendText(DateTime.Now + " Procurando servidores do banco de dados\n\n");
            switch (Environment.GetCommandLineArgs().Length)
            {
                case 2:
                    tboxServidor.Text = Environment.GetCommandLineArgs()[1];
                    bttnIniciar_Click(bttnIniciar, null);
                    break;
                case 3:
                    tboxServidor.Text = Environment.GetCommandLineArgs()[1];
                    switch (Environment.GetCommandLineArgs()[2])
                    {
                        case "1":
                            menu1secInterval_Click(menu1secInterval, null);
                            break;
                        case "5":
                            menu5secInterval_Click(menu5secInterval, null);
                            break;
                        case "15":
                            menu15secInterval_Click(menu15secInterval, null);
                            break;
                        case "60":
                            menu60secInterval_Click(menu60secInterval, null);
                            break;
                        default:
                            menuNoInterval_Click(menuNoInterval, null);
                            break;
                    }
                    bttnIniciar_Click(bttnIniciar, null);
                    break;
                default:
                    ProcurarServidor();
                    break;
            }
        }
    }
}
